#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string>
#include <pthread.h>
#include <fcntl.h>

using namespace std;
#include "serverSocket.h"
#include "serverException.h"
#include "serverThread.h"
#define DEFAULT_PORT 6666
#define DEFAULT_IP "127.0.0.1"


ServerSocket::ServerSocket(){
	printf("start init Server\n");
	listenFd = 0;
	struct sockaddr_in addr; 
	char server_ip[32] = DEFAULT_IP;//6666
    short server_port = DEFAULT_PORT;//"127.0.0.1"
	try{
			//1.Socket系统调用
			listenFd = socket(AF_INET,SOCK_STREAM,0);//第一个参数为AF_INET，第二个参数选SOCK_STREAM，则使用的协议为TCP；
			addr.sin_family = AF_INET;
			addr.sin_port = htons(server_port);
			addr.sin_addr.s_addr = inet_addr(server_ip);
			//2.服务器端Bind系统调用
			//(1)第一个参数socketfd是前步socket()系统调用返回的套节字描述符。 　　(2)第二个参数被捆向本地地址的一种结构
			int res = bind(listenFd,(struct sockaddr*)&addr,sizeof(addr));
			//3.服务器端系统调用listen，使服务器愿意接受连接
			res = listen(listenFd,100);
	}catch(ServerException e){
		printf("%s\n",e.show());
	}
}


ServerSocket::ServerSocket(char *ip,short port){
	printf("start init Server\n");
	listenFd = 0;
	struct sockaddr_in addr; 
	try{
			//1.Socket系统调用
			listenFd = socket(AF_INET,SOCK_STREAM,0);//第一个参数为AF_INET，第二个参数选SOCK_STREAM，则使用的协议为TCP；
			addr.sin_family = AF_INET;
			addr.sin_port = htons(port);
			addr.sin_addr.s_addr = inet_addr(ip);
			//2.服务器端Bind系统调用
			//(1)第一个参数socketfd是前步socket()系统调用返回的套节字描述符。 　　(2)第二个参数被捆向本地地址的一种结构
			int res = bind(listenFd,(struct sockaddr*)&addr,sizeof(addr));
			//3.服务器端系统调用listen，使服务器愿意接受连接
			res = listen(listenFd,100);
	}catch(ServerException e){
		printf("%s\n",e.show());
	}	

}
//析构函数 
ServerSocket::~ServerSocket(){

    close(listenFd);
    close(connectFd);

}
//方法功能:	等待客户端的链接，如果有客户端链接上来，创建客户端线程接收数据
void ServerSocket::acceptClient(){
	while(1){
		
		struct sockaddr_in fromAddr;
		socklen_t len = sizeof(fromAddr);
		try{
		//服务器调用accept,以等待客户机调用connect进行连接
		connectFd = accept(listenFd,(struct sockaddr*) &fromAddr,&len);
		/*
		*该调用取得队列上的第一个连接请求并建立一个具有与sockfd相同特性的套节字。如果没有等待的连接请求，此调用阻塞调用者直到一连接请求到达。
		*连接成功后，该调用将用对端的地址结构和地址长度填充参数peer和addlen，如果对客户端的地址信息不感兴趣，这两个参数用0代替。
		*/
		sleep(1);
		printf("%d\n",connectFd);
		if(connectFd!=-1){	
			printf("accept successful!\n");
			printf("Ready to start to dataMine\n");			
			ServerThread *thread = new ServerThread(connectFd);//创建客户端线程接收数据
			thread->start();//开启客户端线程
		}	
		//捕获并处理异常信息
		
		}catch(ServerException e){
				printf("%s\n",e.show());	
			}
	}	

}